import pandas as pd
import numpy as np
from sklearn.metrics import r2_score
import matplotlib.pyplot as plt
import tensorflow as tf

# shape就是维度的意思

N = 200  # 样本点数目
x = np.linspace(-1, 1, N)  # 生成等差数列分布在[-1, 1]中，类型为<class 'numpy.ndarray'>
y = 2.0*x + np.random.standard_normal(x.shape)*0.3+0.9  # 生成线性数据，最后计算出来的斜率应该接近2.0，类型为<class 'numpy.ndarray'>
print(y)
x = x.reshape([N, 1])  # x由1行N列转换成N行一列，类型为<class 'numpy.ndarray'>
y = y.reshape([N, 1])  # y由1行N列转换成N行一列，类型为<class 'numpy.ndarray'>

plt.scatter(x, y)  # 绘制散点图
# plt.show()  # 展示散点图

# #拆分训练集和测试集
train_size = int(pd.DataFrame(x).shape[0]*0.7)  # DataFrame.shape返回矩阵的维度->(2, 3)，2行3列，直接N * 0.7就行
# print(train_size)

x_train = x[:train_size]
y_train = y[:train_size]
x_test = x[train_size:]
y_test = y[train_size:]

# placeholder预定义
X = tf.placeholder(tf.float32, [None, 1])  # 定义线性回归函数自变量，[None, 1]表示在内存中开辟了一块区域，存储行不受限制的一列数组，类型为<class 'tensorflow.python.framework.ops.Tensor'>
Y = tf.placeholder(tf.float32, [None, 1])  # 定义线性回归函数应变量，[None, 1]表示在内存中开辟了一块区域，存储行不受限制的一列数组，类型为<class 'tensorflow.python.framework.ops.Tensor'>
# 定义W和b
W = tf.Variable(tf.zeros([1, 1]))  # 定义斜率（权重），tf.zeros([1, 1])，1行1列的二维数组，类型为<class 'tensorflow.python.ops.variables.RefVariable'>
b = tf.Variable(tf.zeros([1]))  # 定义截距（偏置），tf.zeros([1])表示一维数组里面放1个值，类型为<class 'tensorflow.python.ops.variables.RefVariable'>

pre = W * X + b  # 定义线性回归函数，类型为<class 'tensorflow.python.framework.ops.Tensor'>

# 计算值与真实值的均方差
cost = tf.reduce_mean(tf.square(Y - pre))  # 类型为<class 'tensorflow.python.framework.ops.Tensor'>
# 通过梯度下降法，在底层调整权重W和偏置b，使得均方误差cost最小
optimizer = tf.train.GradientDescentOptimizer(0.05).minimize(cost)  # 类型为<class 'tensorflow.python.framework.ops.Operation'>

sess = tf.Session()  # 类型为<class 'tensorflow.python.client.session.Session'>
sess.run(tf.global_variables_initializer())  # tf.global_variables_initializer()类型为<class 'tensorflow.python.framework.ops.Operation'>
for step in range(1000):
    # 训练
    sess.run(optimizer, feed_dict={X: x_train, Y: y_train})
    if step % 15 == 0:
        # 损失函数变化
        c = sess.run(cost, feed_dict={X: x_train, Y: y_train})
        print(step, 'cost: ', c)
        # 预测
        pre_y = sess.run(pre, feed_dict={X: x_test})
        score = r2_score(y_test, pre_y)
        print(step, 'R2 score:', score)

# 预测可视化
plt.scatter(x_train, y_train, c='b')
plt.scatter(x_test, pre_y, c='r')
plt.show()
